#include "StdAfx.h"

InputBox* Singleton<InputBox>::m_instance = 0;

InputBox::InputBox(ui32 x, ui32 y, ui32 w, ui32 h) : m_text("Fonts\\Arialn.ttf", "Arial Narrow", 7, 15)
{
	m_position.x = (float)x;
	m_position.y = (float)y;
	m_size.x = (float)w;
	m_size.y = (float)h;

	m_visible = false;
	m_drawCursel = true;

	m_lastChange = 0;

	m_baseVertices1[0].z = m_baseVertices1[1].z = m_baseVertices1[2].z = m_baseVertices1[3].z = 0.0f;
	m_baseVertices1[0].rhw = m_baseVertices1[1].rhw = m_baseVertices1[2].rhw = m_baseVertices1[3].rhw = 1.0f;
	m_baseVertices1[0].x = m_position.x;
	m_baseVertices1[0].y = m_position.y;
	m_baseVertices1[0].u = 0.0f;
	m_baseVertices1[0].v = 0.0f;

	m_baseVertices1[1].x = m_position.x + m_size.x / 2;
	m_baseVertices1[1].y = m_position.y;
	m_baseVertices1[1].u = 1.0f;
	m_baseVertices1[1].v = 0.0f;

	m_baseVertices1[2].x = m_position.x + m_size.x / 2;
	m_baseVertices1[2].y = m_position.y + m_size.y;
	m_baseVertices1[2].u = 1.0f;
	m_baseVertices1[2].v = 1.0f;

	m_baseVertices1[3].x = m_position.x;
	m_baseVertices1[3].y = m_position.y + m_size.y;
	m_baseVertices1[3].u = 0.0f;
	m_baseVertices1[3].v = 1.0f;

	m_baseVertices2[0].z = m_baseVertices2[1].z = m_baseVertices2[2].z = m_baseVertices2[3].z = 0.0f;
	m_baseVertices2[0].rhw = m_baseVertices2[1].rhw = m_baseVertices2[2].rhw = m_baseVertices2[3].rhw = 1.0f;
	m_baseVertices2[0].x = m_position.x + m_size.x / 2 - 1;
	m_baseVertices2[0].y = m_position.y;
	m_baseVertices2[0].u = 1.0f;
	m_baseVertices2[0].v = 0.0f;

	m_baseVertices2[1].x = m_position.x + m_size.x - 1;
	m_baseVertices2[1].y = m_position.y;
	m_baseVertices2[1].u = 0.0f;
	m_baseVertices2[1].v = 0.0f;

	m_baseVertices2[2].x = m_position.x + m_size.x - 1;
	m_baseVertices2[2].y = m_position.y + m_size.y;
	m_baseVertices2[2].u = 0.0f;
	m_baseVertices2[2].v = 1.0f;

	m_baseVertices2[3].x = m_position.x + m_size.x / 2 - 1;
	m_baseVertices2[3].y = m_position.y + m_size.y;
	m_baseVertices2[3].u = 1.0f;
	m_baseVertices2[3].v = 1.0f;

	m_baseTexture1 = CTextureHandler::GetInstance()->GetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Left.blp");

	m_linePoints[0].z = m_linePoints[1].z = m_linePoints[2].z = m_linePoints[3].z = 0.0f;
	m_linePoints[0].rhw = m_linePoints[1].rhw = m_linePoints[2].rhw = m_linePoints[3].rhw = 1.0f;

	m_linePoints[0].x = m_position.x + 12;
	m_linePoints[0].y = m_position.y + 11;
	m_linePoints[1].x = m_position.x + 13;
	m_linePoints[1].y = m_position.y + 11;
	m_linePoints[2].x = m_position.x + 13;
	m_linePoints[2].y = m_position.y + m_size.y - 11;
	m_linePoints[3].x = m_position.x + 12;
	m_linePoints[3].y = m_position.y + m_size.y - 11;
	m_linePoints[4] = m_linePoints[0];
	
	for(ui32 i = 0; i < 5; ++i)
		m_linePoints[i].dwColor = 0xFFFFFFFF;

	m_focus = false;
	m_szText = "";
	m_szRenderText = "";
	m_curLength = 0;
	m_historyPoint = -1;
	m_history.clear();
}

void InputBox::Draw()
{
	if(!m_visible || sD3D.GetAppState() != STATE_WORLD)
		return;
	sD3D->SetFVF(VERTEX3FRHWT);
	sD3D->SetTexture(0, *m_baseTexture1);
	sD3D->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, m_baseVertices1, sizeof(Vertex3FRHWT));
	//sD3D->SetTexture(0, *m_baseTexture2);
	sD3D->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, m_baseVertices2, sizeof(Vertex3FRHWT));

	m_text.DrawTextA(ui32(m_position.x + 12), ui32(m_position.y + 8), m_text.GetTextLen(m_szRenderText), ui32(m_size.y), m_szRenderText);

	if(!m_lastChange)
	{
		m_drawCursel = true;
		m_lastChange = GetTickCount();
	}
	else
	{
		ui32 now = GetTickCount();
		if(now - m_lastChange >= 1000 && m_drawCursel)
		{
			m_drawCursel = !m_drawCursel;
			m_lastChange = now;
		}
		else if(now - m_lastChange >= 750 && !m_drawCursel)
		{
			m_drawCursel = !m_drawCursel;
			m_lastChange = now;
		}
	}

	if(m_drawCursel && m_focus)
	{
		sD3D->SetTexture(0, 0);
		sD3D->SetFVF(VERTEX3FRHWC);
		sD3D->DrawPrimitiveUP(D3DPT_LINESTRIP, 4, m_linePoints, sizeof(Vertex3FRHWC));
	}
}

void InputBox::OnEnterPressed()
{
	m_visible = !m_visible;
	if(m_visible)
		m_focus = true;
}

void InputBox::MouseActivity(bool left, Vertex2F pos, bool up)
{
	if(!m_visible)
	{
		m_focus = false;
		return;
	}

	if(pos.x >= m_position.x + 12 && pos.x <= (m_position.x + m_size.x - 12) &&
		pos.y >= m_position.y + 11 && pos.y <= (m_position.y + m_size.y - 11))
		m_focus = true;
	else
		m_focus = false;
}

void InputBox::OnVirtualKey(char vKey)
{
	if(!m_focus)
		return;
	if(vKey == VK_UP)
	{
		if(m_historyPoint < (i32)m_history.size() && m_history.size())
		{
			if(m_historyPoint == -1)
			{
				m_szText = m_history[0];
				m_historyPoint = 0;
			}
			else
			{
				if(m_historyPoint + 1 < (i32)m_history.size())
				{
					m_szText = m_history[++m_historyPoint];
				}
				else
					return;
			}
			m_szRenderText = m_szText;
			bool toLong = false;
			while(m_text.GetTextLen(m_szRenderText, true) > m_size.x - 22)
			{
				toLong = true;
				m_szRenderText.erase(m_szRenderText.begin());
			}
			for(ui32 i = 0; i < 5; ++i)
				m_linePoints[i].x = m_position.x + 12 + m_text.GetTextLen(m_szRenderText, true);
		}
		return;
	}
	if(vKey == VK_DOWN)
	{
		if(m_historyPoint > 0u && m_historyPoint <= (i32)m_history.size())
		{
			m_szText = m_history[--m_historyPoint];
			m_szRenderText = m_szText;
			bool toLong = false;
			while(m_text.GetTextLen(m_szRenderText, true) > m_size.x - 22)
			{
				toLong = true;
				m_szRenderText.erase(m_szRenderText.begin());
			}
			for(ui32 i = 0; i < 5; ++i)
				m_linePoints[i].x = m_position.x + 12 + m_text.GetTextLen(m_szRenderText, true);
		}
		return;
	}
}

void InputBox::OnKey(char key)
{
	if(!m_focus || !m_visible)
		return;
	if(key == VK_ESCAPE)
	{
		m_focus = false;
		return;
	}
	if(key == '\b')
	{
		if(m_szText.length() == 0)
			return;

		ui32 lenAtEnd = m_text.GetCharWidthA(m_szText.at(m_szText.size() - 1));
		m_szText.resize(m_szText.size() - 1);
		m_szRenderText = m_szText;
		bool toLong = false;
		while(m_text.GetTextLen(m_szRenderText, true) > m_size.x - 22)
		{
			toLong = true;
			m_szRenderText.erase(m_szRenderText.begin());
		}
		if(!toLong)
		{
			for(ui32 i = 0; i < 5; ++i)
				m_linePoints[i].x = m_position.x + 12 + m_text.GetTextLen(m_szRenderText, true);
		}
		return;
	}
	if(key == '\r')
	{
		sCommand.HandleInput(m_szText);
		m_history.push_front(m_szText);
		m_historyPoint = -1;
		while(m_history.size() > 30)
			m_history.pop_back();
		m_szText = "";
		m_szRenderText = "";
		for(ui32 i = 0; i < 5; ++i)
			m_linePoints[i].x = m_position.x + 12;
		return;
	}
	if(key < 20)
		return;
	m_szText += key;
	m_szRenderText = m_szText;
	bool toLong = false;
	while(m_text.GetTextLen(m_szRenderText, true) > m_size.x - 22)
	{
		toLong = true;
		m_szRenderText.erase(m_szRenderText.begin());
	}
	if(!toLong)
	{
		for(ui32 i = 0; i < 5; ++i)
			m_linePoints[i].x = m_position.x + 12 + m_text.GetTextLen(m_szRenderText, true);
	}
}